Android Architecture Samplesを読む
intent-fileter内に該当設定があるアクティビティは、com.example.android.architecture.blueprints.todoapp.TodoActivityだ
単画面アプリ
code:TodoActivity.kt
@AndroidEntryPoint
class TodoActivity : ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent {
AppCompatTheme {
TodoNavGraph()
}
}
}
}
どうして単一のActivityなのだろうか
複数アクティビティだと、NavGraphによる一元管理ができない?
TodoNavGraphを呼んでいるので、そこを読みに行く
code:TodoNavGraph.kt
@Composable
fun TodoNavGraph(
modifier: Modifier = Modifier,
navController: NavHostController = rememberNavController(),
coroutineScope: CoroutineScope = rememberCoroutineScope(),
drawerState: DrawerState = rememberDrawerState(initialValue = DrawerValue.Closed),
startDestination: String = TodoDestinations.TASKS_ROUTE,
navActions: TodoNavigationActions = remember(navController) {
TodoNavigationActions(navController)
}
) {
val currentNavBackStackEntry by navController.currentBackStackEntryAsState()
val currentRoute = currentNavBackStackEntry?.destination?.route ?: startDestination
NavHost(
navController = navController,
startDestination = startDestination,
modifier = modifier
) {
composable(
TodoDestinations.TASKS_ROUTE,
arguments = listOf(
navArgument(USER_MESSAGE_ARG) { type = NavType.IntType; defaultValue = 0 }
)
) { entry ->
AppModalDrawer(drawerState, currentRoute, navActions) {
TasksScreen(
userMessage = entry.arguments?.getInt(USER_MESSAGE_ARG)!!,
onUserMessageDisplayed = { entry.arguments?.putInt(USER_MESSAGE_ARG, 0) },
onAddTask = { navActions.navigateToAddEditTask(R.string.add_task, null) },
onTaskClick = { task -> navActions.navigateToTaskDetail(task.id) },
openDrawer = { coroutineScope.launch { drawerState.open() } }
)
}
}
composable(TodoDestinations.STATISTICS_ROUTE) {
AppModalDrawer(drawerState, currentRoute, navActions) {
StatisticsScreen(openDrawer = { coroutineScope.launch { drawerState.open() } })
}
}
composable(
TodoDestinations.ADD_EDIT_TASK_ROUTE,
arguments = listOf(
navArgument(TITLE_ARG) { type = NavType.IntType },
navArgument(TASK_ID_ARG) { type = NavType.StringType; nullable = true },
)
) { entry ->
val taskId = entry.arguments?.getString(TASK_ID_ARG)
AddEditTaskScreen(
topBarTitle = entry.arguments?.getInt(TITLE_ARG)!!,
onTaskUpdate = {
navActions.navigateToTasks(
if (taskId == null) ADD_EDIT_RESULT_OK else EDIT_RESULT_OK
)
},
onBack = { navController.popBackStack() }
)
}
composable(TodoDestinations.TASK_DETAIL_ROUTE) {
TaskDetailScreen(
onEditTask = { taskId ->
navActions.navigateToAddEditTask(R.string.edit_task, taskId)
},
onBack = { navController.popBackStack() },
onDeleteTask = { navActions.navigateToTasks(DELETE_RESULT_OK) }
)
}
}
}
NavHostが主役
Destinationとして、Composableが複数定義されている
それぞれEnumで定義されたルートを持ち、Composableを呼び出す
呼び出しているComposable
AppModalDrawerで包んだStatisticsScreen
AppModalDrawerで包んだTasksScreen
AddEditTaskScreen
TaskDetailScreen
AppModalDrawerってなんだ?
code:TodoDwawer.kt
@Composable
fun AppModalDrawer(
drawerState: DrawerState,
currentRoute: String,
navigationActions: TodoNavigationActions,
coroutineScope: CoroutineScope = rememberCoroutineScope(),
content: @Composable () -> Unit
) {
ModalDrawer(
drawerState = drawerState,
drawerContent = {
AppDrawer(
currentRoute = currentRoute,
navigateToTasks = { navigationActions.navigateToTasks() },
navigateToStatistics = { navigationActions.navigateToStatistics() },
closeDrawer = { coroutineScope.launch { drawerState.close() } }
)
}
) {
content()
}
}
ModalDrawerでAppDrawerを包んだやつだ
今は、データ層へとUI層へのアクセスに興味がある
関連していそうなところ
TaskScreenはタスクのデータにアクセスしているだろう
いや、嘘
UIとデータアクセスは分離されているはず
TaskScreenの引数をみよう
ViewModelがUIの情報を管理している
TaskViewModelというクラス
見に行く